home *** CD-ROM | disk | FTP | other *** search
/ C/C++ Users Group Library 1996 July / C-C++ Users Group Library July 1996.iso / listings / v_10_08 / 1008038a < prev    next >
Text File  |  1992-05-28  |  17KB  |  422 lines

  1. /* RAY_RAD - A Very Simple Ray-Traced Radiosity Renderer        */
  2.  
  3. #include <stdio.h>
  4. #include <stdlib.h>
  5. #include <math.h>
  6.  
  7. #define FLOOR           0       /* X-Y plane, Z = 0.0           */
  8. #define SOUTH_WALL      1       /* X-Z plane, Y = 0.0           */
  9. #define EAST_WALL       2       /* Y-Z plane, X = 8.0           */
  10. #define NORTH_WALL      3       /* X-Z plane, Y = 8.0           */
  11. #define WEST_WALL       4       /* X-Z plane, X = 0.0           */
  12. #define MAX_RAYS        25000   /* Maximum number of rays       */
  13. #define MAX_VAL         1.0e+6  /* Maximum floating point value */
  14. #define MIN_VAL         1.0e-6  /* Minimum floating point value */
  15. #define NUM_LOOP        20      /* Number of iterations         */
  16. #define NUM_SURF        10      /* Number of surfaces           */
  17. #define PI              3.141592654
  18. #define DRAND()         ((double) rand() / (double) RAND_MAX)
  19.  
  20. typedef struct          /* 3-D point co-ordinates               */
  21. {
  22.   double x;             /* X-axis co-ordinate                   */
  23.   double y;             /* Y-axis co-ordinate                   */
  24.   double z;             /* Z-axis co-ordinate                   */
  25. } PT_3D;
  26.  
  27. typedef struct          /* 3-D ray                              */
  28. {
  29.   PT_3D org;            /* Origin                               */
  30.   PT_3D dir;            /* Direction                            */
  31. } RAY;
  32.  
  33. typedef struct          /* Element                              */
  34. {
  35.   double total;         /* Total flux                           */
  36.   double unsent;        /* Unsent flux                          */
  37. } ELEM;
  38.  
  39. typedef struct          /* Surface                              */
  40. {
  41.   PT_3D vertex[4];      /* Vertex array                         */
  42.   int num_row;          /* Number of element rows               */
  43.   int num_col;          /* Number of element columns            */
  44.   double col_dim;       /* Element column dimension             */
  45.   double row_dim;       /* Element row dimension                */
  46.   double emittance;     /* Emittance                            */
  47.   double reflectance;   /* Reflectance                          */
  48.   ELEM *elemp;          /* Element array pointer                */
  49. } SURF;
  50.  
  51. static int send_flux(int, int, int);
  52. static void display_surface(void);
  53. static void find_element(RAY *, int *, int *, int *);
  54. static void global_to_local(int, PT_3D *, PT_3D *);
  55. static void local_to_global(int, RAY *, RAY *);
  56. static void select_ray(int, int, int, RAY *);
  57.  
  58. static double MaxEmittance = 0.0;       /* Maximum emittance    */
  59. static SURF RoomSurf[NUM_SURF] = {      /* Room surfaces        */
  60.   { { { 0.0, 0.0, 0.0 }, { 8.0, 0.0, 0.0 },     /* Floor        */
  61.     { 8.0, 8.0, 0.0 }, { 0.0, 8.0, 0.0 } }, 8, 8, 1.0, 1.0,
  62.        0.0, 0.2, NULL },
  63.   { { { 0.0, 0.0, 0.0 }, { 0.0, 0.0, 8.0 },     /* South wall   */
  64.     { 8.0, 0.0, 8.0 }, { 8.0, 0.0, 0.0 } }, 8, 8, 1.0, 1.0,
  65.        0.0, 0.5, NULL },
  66.   { { { 8.0, 0.0, 0.0 }, { 8.0, 0.0, 8.0 },     /* East wall    */
  67.     { 8.0, 8.0, 8.0 }, { 8.0, 8.0, 0.0 } }, 8, 8, 1.0, 1.0,
  68.        0.0, 0.5, NULL },
  69.   { { { 8.0, 8.0, 0.0 }, { 8.0, 8.0, 8.0 },     /* North wall   */
  70.     { 0.0, 8.0, 8.0 }, { 0.0, 8.0, 0.0 } }, 8, 8, 1.0, 1.0,
  71.        0.0, 0.5, NULL },
  72.   { { { 0.0, 8.0, 0.0 }, { 0.0, 8.0, 8.0 },     /* West wall    */
  73.     { 0.0, 0.0, 8.0 }, { 0.0, 0.0, 0.0 } }, 8, 8, 1.0, 1.0,
  74.        0.0, 0.5, NULL },
  75.   { { { 0.0, 0.0, 8.0 }, { 0.0, 3.0, 8.0 },     /* South ceil.  */
  76.     { 8.0, 3.0, 8.0 }, { 8.0, 0.0, 8.0 } }, 8, 3, 1.0, 1.0,
  77.        0.0, 0.8, NULL },
  78.   { { { 5.0, 3.0, 8.0 }, { 5.0, 5.0, 8.0 },     /* East ceiling */
  79.     { 8.0, 5.0, 8.0 }, { 8.0, 3.0, 8.0 } }, 3, 2, 1.0, 1.0,
  80.        0.0, 0.8, NULL },
  81.   { { { 0.0, 5.0, 8.0 }, { 0.0, 8.0, 8.0 },     /* North ceil.  */
  82.     { 8.0, 8.0, 8.0 }, { 8.0, 5.0, 8.0 } }, 8, 3, 1.0, 1.0,
  83.        0.0, 0.8, NULL },
  84.   { { { 0.0, 3.0, 8.0 }, { 0.0, 5.0, 8.0 },     /* West ceiling */
  85.     { 3.0, 5.0, 8.0 }, { 3.0, 3.0, 8.0 } }, 3, 2, 1.0, 1.0,
  86.        0.0, 0.8, NULL },
  87.   { { { 3.0, 3.0, 8.0 }, { 3.0, 5.0, 8.0 },     /* Ceil. light  */
  88.     { 5.0, 5.0, 8.0 }, { 5.0, 3.0, 8.0 } }, 2, 2, 1.0, 1.0,
  89.     5000.0, 0.8, NULL } };
  90.  
  91. int main(void)
  92. {
  93.   int col;              /* Column counter                       */
  94.   int elem;             /* Element counter                      */
  95.   int maximum;          /* Maximum number of rays               */
  96.   int num_elem;         /* Number of elements                   */
  97.   int num_rays;         /* Number of rays                       */
  98.   int row;              /* Row counter                          */
  99.   int surf;             /* Surface counter                      */
  100.   ELEM *elemp;          /* Element pointer                      */
  101.   SURF *surfp;          /* Surface pointer                      */
  102.  
  103.   for (surf = 0; surf < NUM_SURF; surf++) {
  104.     /* Instantiate elements                                     */
  105.     surfp = &(RoomSurf[surf]);
  106.     num_elem = surfp->num_row * surfp->num_col;
  107.     if ((surfp->elemp = (ELEM *) malloc(num_elem * sizeof(ELEM)))
  108.         == NULL) {
  109.       fputs("Out of memory!\n", stderr);
  110.       return (2);
  111.     }
  112.  
  113.     elemp = surfp->elemp;
  114.     for (elem = 0; elem < num_elem; elem++, elemp++)
  115.       elemp->total = elemp->unsent = surfp->emittance;
  116.  
  117.     if (surfp->emittance > MaxEmittance)
  118.       MaxEmittance = surfp->emittance;
  119.   }
  120.  
  121.   do {
  122.     /* Distribute flux between elements                         */
  123.     num_rays = 0;
  124.     for (surf = 0; surf < NUM_SURF; surf++) {
  125.       surfp = &(RoomSurf[surf]);
  126.       for (row = 0; row < surfp->num_row; row++)
  127.         for (col = 0; col < surfp->num_col; col++) {
  128.           if ((maximum = send_flux(surf, row, col)) > num_rays)
  129.             num_rays = maximum;
  130.         }
  131.     }
  132.     display_surface();          /* Display intermediate results */
  133.   } while (num_rays > 0);       /* Repeat until convergence     */
  134.  
  135.   for (surf = 0; surf < NUM_SURF; surf++)       /* Free memory  */
  136.     free(RoomSurf[surf].elemp);
  137.  
  138.   return (0);
  139. }
  140.  
  141. static int send_flux (  /* Send flux to other elements          */
  142.   int s_surf,           /* Sending surface index                */
  143.   int s_row,            /* Sending element row                  */
  144.   int s_col )           /* Sending element column               */
  145. {
  146.   int h_col;            /* Hit element column                   */
  147.   int h_row;            /* Hit element row                      */
  148.   int h_surf;           /* Hit surface index                    */
  149.   int num_rays;         /* Number of rays                       */
  150.   int ray;              /* Ray counter                          */
  151.   double inc_flux;      /* Incident (ray) flux                  */
  152.   double ref_flux;      /* Reflected flux                       */
  153.   RAY shoot;            /* Shooting ray                         */
  154.   ELEM *h_elemp;        /* Hit element pointer                  */
  155.   ELEM *s_elemp;        /* Sending element pointer              */
  156.   SURF *h_surfp;        /* Hit surface pointer                  */
  157.   SURF *s_surfp;        /* Sending surface pointer              */
  158.  
  159.   s_surfp = &(RoomSurf[s_surf]);
  160.   s_elemp = s_surfp->elemp + s_row * s_surfp->num_col + s_col;
  161.  
  162.   /* Number of rays to shoot proportional to unsent flux        */
  163.   if ((num_rays = (int) (MAX_RAYS * s_elemp->unsent /
  164.       MaxEmittance)) == 0)
  165.     return (0);
  166.  
  167.   inc_flux = s_elemp->unsent / num_rays;    /* Get ray flux     */
  168.  
  169.   for (ray = 0; ray < num_rays; ray++) {    /* Distribute flux  */
  170.     select_ray(s_surf, s_row, s_col, &shoot);   /* Select ray   */
  171.  
  172.     /* Find hit surface and element                             */
  173.     find_element(&shoot, &h_surf, &h_row, &h_col);
  174.  
  175.     /* Calculate flux reflected from hit element                */
  176.     h_surfp = &(RoomSurf[h_surf]);
  177.     h_elemp = h_surfp->elemp + h_row * h_surfp->num_col + h_col;
  178.     ref_flux = h_surfp->reflectance * inc_flux;
  179.  
  180.     h_elemp->total += ref_flux;         /* Update total flux    */
  181.     h_elemp->unsent += ref_flux;        /* Update unsent flux   */
  182.   }
  183.  
  184.   s_elemp->unsent = 0.0;    /* Res